Introduction
This rmd. file imports oxygen and voltage data from Google sheet Data
is used to plot a oxygen and voltage gradient map of the winogradsky
column Exponential and linear models were used to analyze data
Loading Packages
library(tidyverse)
library(googledrive)
library(googlesheets4)
#library(ggplot2)
library(knitr)
library(minpack.lm)
library(broom)
library(purrr)
library(lme4)
library(patchwork)
<<<<<<< HEAD
=======
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
Importing from google sheet
googlesheets4::gs4_deauth()
CleanData_Oxygen <- googlesheets4::read_sheet("https://docs.google.com/spreadsheets/d/1hNakCyqPsTNRFpf1lGjoBQ-papyZ6xHKT6mcvh3LMb8/edit?pli=1&gid=842906991#gid=842906991", "CleanData_Oxygen") |>
mutate(Sample = as.character(Sample))
✔ Reading from Microcosms.
✔ Range ''CleanData_Oxygen''.
kable(CleanData_Oxygen)
| 1004 |
0.0 |
276.0 |
21.2 |
| 1004 |
6.2 |
276.0 |
21.2 |
| 1004 |
8.4 |
275.0 |
21.2 |
| 1004 |
13.1 |
6.3 |
21.2 |
| 1004 |
22.0 |
3.4 |
21.2 |
| 1003 |
0.0 |
101.0 |
20.0 |
| 1003 |
5.8 |
62.0 |
20.0 |
| 1003 |
8.4 |
52.0 |
20.0 |
| 1003 |
13.1 |
29.0 |
20.0 |
| 1003 |
21.3 |
21.0 |
20.0 |
| 1002 |
0.0 |
80.0 |
19.8 |
| 1002 |
6.6 |
45.0 |
19.8 |
| 1002 |
9.3 |
26.0 |
19.8 |
| 1002 |
15.1 |
21.0 |
19.8 |
| 1002 |
21.9 |
19.0 |
19.8 |
| 1001_C |
0.0 |
190.0 |
19.0 |
| 1001_C |
6.9 |
106.0 |
19.0 |
| 1001_C |
10.8 |
99.0 |
19.0 |
| 1001_C |
16.6 |
57.0 |
19.0 |
| 1001_C |
22.7 |
25.0 |
19.0 |
| 1001_W |
0.0 |
103.0 |
19.0 |
| 1001_W |
6.7 |
34.0 |
19.0 |
| 1001_W |
10.2 |
21.0 |
19.0 |
| 1001_W |
15.2 |
11.0 |
19.0 |
| 1001_W |
22.8 |
8.0 |
19.0 |
googlesheets4::gs4_deauth()
CleanData_Voltage <- googlesheets4::read_sheet("https://docs.google.com/spreadsheets/d/1hNakCyqPsTNRFpf1lGjoBQ-papyZ6xHKT6mcvh3LMb8/edit?pli=1&gid=842906991#gid=842906991", "CleanData_Voltage") |>
mutate(Sample = as.character(Sample))
✔ Reading from Microcosms.
✔ Range ''CleanData_Voltage''.
kable(CleanData_Voltage)
| 1004 |
0.0 |
NA |
NA |
121.0 |
121.0 |
| 1004 |
6.2 |
160.2 |
190 |
-168.0 |
-168.0 |
| 1004 |
8.4 |
74.4 |
79 |
84.0 |
122.0 |
| 1004 |
13.1 |
-55.0 |
58 |
43.0 |
51.0 |
| 1004 |
22.0 |
-200.0 |
204 |
84.0 |
102.0 |
| 1003 |
0.0 |
NA |
NA |
74.0 |
300.0 |
| 1003 |
5.8 |
27.0 |
27 |
-13.0 |
26.0 |
| 1003 |
8.4 |
59.0 |
83 |
57.0 |
57.0 |
| 1003 |
13.1 |
-20.0 |
101 |
-94.0 |
-136.0 |
| 1003 |
21.3 |
-25.0 |
-30 |
161.0 |
177.0 |
| 1002 |
0.0 |
NA |
NA |
51.0 |
199.0 |
| 1002 |
6.6 |
-39.0 |
-40 |
13.0 |
30.0 |
| 1002 |
9.3 |
-4.3 |
30 |
196.0 |
199.0 |
| 1002 |
15.1 |
24.0 |
-4 |
16.0 |
25.0 |
| 1002 |
21.9 |
27.0 |
28 |
194.0 |
199.0 |
| 1001_C |
0.0 |
NA |
NA |
187.0 |
187.0 |
| 1001_C |
6.9 |
-10.0 |
-22 |
76.0 |
300.0 |
| 1001_C |
10.8 |
25.0 |
60 |
-2.8 |
-2.8 |
| 1001_C |
16.6 |
-6.0 |
-23 |
-10.5 |
-3.0 |
| 1001_C |
22.7 |
6.0 |
48 |
168.0 |
174.0 |
| 1001_W |
0.0 |
NA |
NA |
187.0 |
187.0 |
| 1001_W |
6.7 |
16.0 |
-9 |
13.0 |
170.0 |
| 1001_W |
10.2 |
31.0 |
33 |
-48.0 |
-48.0 |
| 1001_W |
15.2 |
34.0 |
40 |
24.0 |
24.0 |
| 1001_W |
22.8 |
40.0 |
-17 |
72.0 |
72.0 |
Combine O2 & Voltage data by sample & depth
Gradients <- left_join(x = CleanData_Oxygen, y = CleanData_Voltage, by = c("Sample", "Depth_cm"))
Oxygen Gradient Plot
ggplot(data = CleanData_Oxygen) +
geom_point(aes(y = DO_µg_L, x = Depth_cm)) +
#scale_y_reverse() +
#labs( title= "Oxygen Gradients", caption= "Figure X. Dissolved Oxygen (DO) (µg/L) measured in four Winogradsky colums at 5 depths (cm)")
#+ theme(plot.caption= element_text(size = 11, hjust=0)) +
#geom_path(aes(y = Depth_cm, x = DO_µg_L)) +
facet_grid(cols = vars(Sample)) +
theme_bw()

#+ scale_y_continuous(limits = c(0, 300))
#define exponential decay function for data fitting.
exp_decay <- function(x, i, mu){y = i * exp(mu * x)}
O2_nest <- CleanData_Oxygen |> #alternate forward pipe is %>% loaded with tidyverse
nest(.by = "Sample") |>
mutate(DecayFit = purrr::map(data, ~nlsLM(DO_µg_L ~ exp_decay(x = Depth_cm, i, mu),
data = .x)),
DecayTidy = purrr::map(DecayFit, tidy),
DecayParam = purrr::map(DecayFit, glance),
DecayPredict = purrr::map(DecayFit, augment)
)
Warning: There were 5 warnings in `mutate()`.
The first warning was:
ℹ In argument: `DecayFit = purrr::map(...)`.
Caused by warning in `nlsLM()`:
! No starting values specified for some parameters.
Initializing ‘i’, ‘mu’ to '1.'.
Consider specifying 'start' or using a selfStart model
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 4 remaining warnings.
O2_nest |>
unnest(cols = c(DecayPredict)) |>
ggplot() +
geom_point(aes(x = Depth_cm, y = DO_µg_L)) +
geom_line(aes(x = Depth_cm, y = .fitted)) +
geom_point(aes(x = Depth_cm, y = .resid), colour = "red") +
facet_grid(cols = vars(unlist(Sample))) +
theme_bw()

O2_nest |>
unnest(cols = c(DecayTidy)) |>
select(-c(data, DecayFit, DecayParam, DecayPredict)) |>
select(-c(statistic)) |>
pivot_wider(id_cols = Sample, names_from = term, values_from = c(estimate, std.error, p.value)) |>
kable()
| 1004 |
326.62310 |
-0.0779518 |
101.553081 |
0.0494649 |
0.0487222 |
0.2131346 |
| 1003 |
100.85694 |
-0.0833277 |
3.557277 |
0.0059295 |
0.0000963 |
0.0007804 |
| 1002 |
78.61257 |
-0.0897172 |
6.441339 |
0.0139884 |
0.0011845 |
0.0076805 |
| 1001_C |
190.11905 |
-0.0743515 |
10.391455 |
0.0078457 |
0.0003563 |
0.0024909 |
| 1001_W |
102.49196 |
-0.1553412 |
3.251191 |
0.0097456 |
0.0000701 |
0.0005369 |
Voltage Gradient Plot
<<<<<<< HEAD
=======
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
ggplot(data = Gradients) +
geom_point(aes(x = Depth_cm, y = Voltage_Water_10s_mv)) +
facet_grid(cols = vars(Sample)) +
theme_bw()
<<<<<<< HEAD

=======

>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
<<<<<<< HEAD
=======
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
Linear_fit <- Gradients %>%
group_by(Sample) %>%
group_modify(~ {
linear <- lm(Voltage_Water_10s_mv ~ Depth_cm, data = .x, na.action = na.exclude)
augment(linear, data = .x)}) %>%
ungroup()
Linear_fit |>
ggplot(aes(x = Depth_cm, y = Voltage_Water_10s_mv)) +
geom_point() +
geom_line(aes(y = .fitted)) +
#Showing residuals
#geom_point(aes(x = Depth_cm, y = .resid), colour = "red") +
geom_segment(aes(xend = Depth_cm, yend = .fitted), color = "red") +
facet_grid(cols = vars(unlist(Sample))) +
theme_bw()
<<<<<<< HEAD

=======

>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
NA
NA
<<<<<<< HEAD
Linear_fit_param <- Linear_fit |>
group_by(Sample) |>
group_modify(~ {
=======
Linear_fit_results <- Linear_fit |>
group_by(Sample) |>
group_modify(~ {
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
linear_model <- lm(Voltage_Water_10s_mv ~ Depth_cm, data = .x)
tidy_model <- tidy(linear_model)
tidy_model$Sample <- unique(.x$Sample) # Ensure Sample column is added
return(tidy_model)
<<<<<<< HEAD
}) |>
ungroup()
=======
}) |>
ungroup() |>
# Filter for 'Depth_cm' coefficient (we are examining Voltage in terms of Depth_cm)
filter(term == "Depth_cm")
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
Warning: Unknown or uninitialised column: `Sample`.Warning: Unknown or uninitialised column: `Sample`.Warning: Unknown or uninitialised column: `Sample`.Warning: Unknown or uninitialised column: `Sample`.Warning: Unknown or uninitialised column: `Sample`.
Linear_fit_param <- Linear_fit_param |>
mutate(term = str_replace(term, "\\(Intercept\\)", "I"))
Linear_fit_param |>
select(-c(statistic)) |>
pivot_wider(id_cols = Sample, names_from = term, values_from = c(estimate, std.error, p.value)) |>
kable()
<<<<<<< HEAD
=======
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
| 1001_C |
1.370844 |
0.1669583 |
24.814453 |
1.6058696 |
0.9609665 |
0.9266817 |
| 1001_W |
12.287870 |
1.3087162 |
6.912976 |
0.4609137 |
0.2174605 |
0.1048823 |
| 1002 |
-51.186449 |
4.0159886 |
21.382850 |
1.4776076 |
0.1390247 |
0.1129043 |
| 1003 |
66.227753 |
-4.6072225 |
34.968252 |
2.5893530 |
0.1987344 |
0.2171558 |
| 1004 |
269.340131 |
-22.0877369 |
39.168813 |
2.8330251 |
0.0205004 |
0.0160561 |
NA
<<<<<<< HEAD
Oxygen and Voltage Gradients
=======
Oxygen vs Voltage Graphs
>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
Oxygen <- ggplot(data = Gradients) +
geom_point(aes(x = Depth_cm, y = DO_µg_L)) +
facet_grid(cols = vars(Sample)) +
theme_bw()
Voltage <- ggplot(data = Gradients) +
geom_point(aes(x = Depth_cm, y = Voltage_Water_10s_mv)) +
facet_grid(cols = vars(Sample)) +
theme_bw()
print(Oxygen/Voltage)
<<<<<<< HEAD

=======

>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
NA
NA
<<<<<<< HEAD
=======
ggplot(data = Gradients) +
geom_point(aes(x = DO_µg_L, y = Voltage_Water_10s_mv)) +
geom_smooth(aes(x = DO_µg_L, y = Voltage_Water_10s_mv), method = "lm") +
facet_grid(cols = vars(Sample)) +
theme_bw()

Can only import one image at a time right now, we could choose some
notable ones to display?

>>>>>>> 3aa3cf52183a46ab8b522112e7770a3bf6725159
LS0tCnRpdGxlOiAiT3h5Z2VuJlZvbHRhZ2VfZ3JhZGllbnRzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIEludHJvZHVjdGlvbgoKVGhpcyBybWQuIGZpbGUgaW1wb3J0cyBveHlnZW4gYW5kIHZvbHRhZ2UgZGF0YSBmcm9tIEdvb2dsZSBzaGVldApEYXRhIGlzIHVzZWQgdG8gcGxvdCBhIG94eWdlbiBhbmQgdm9sdGFnZSBncmFkaWVudCBtYXAgb2YgdGhlIHdpbm9ncmFkc2t5IGNvbHVtbiAKRXhwb25lbnRpYWwgYW5kIGxpbmVhciBtb2RlbHMgd2VyZSB1c2VkIHRvIGFuYWx5emUgZGF0YQoKIyMgTG9hZGluZyBQYWNrYWdlcyAKCmBgYHtyIGxvYWRpbmcgcGFja2FnZXN9CmxpYnJhcnkodGlkeXZlcnNlKSAKbGlicmFyeShnb29nbGVkcml2ZSkgCmxpYnJhcnkoZ29vZ2xlc2hlZXRzNCkKI2xpYnJhcnkoZ2dwbG90MikKbGlicmFyeShrbml0cikKbGlicmFyeShtaW5wYWNrLmxtKQpsaWJyYXJ5KGJyb29tKQpsaWJyYXJ5KHB1cnJyKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkocGF0Y2h3b3JrKQpgYGAKCiMjIEltcG9ydGluZyBmcm9tIGdvb2dsZSBzaGVldAoKYGBge3IgbG9hZCBDbGVhbk94eWdlbkRhdGEgZGlyZWN0IGZyb20gZ29vZ2xlc2hlZXR9Cgpnb29nbGVzaGVldHM0OjpnczRfZGVhdXRoKCkKCkNsZWFuRGF0YV9PeHlnZW4gPC0gZ29vZ2xlc2hlZXRzNDo6cmVhZF9zaGVldCgiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMWhOYWtDeXFQc1ROUkZwZjFsR2pvQlEtcGFweVo2eEhLVDZtY3ZoM0xNYjgvZWRpdD9wbGk9MSZnaWQ9ODQyOTA2OTkxI2dpZD04NDI5MDY5OTEiLCAiQ2xlYW5EYXRhX094eWdlbiIpIHw+CiAgbXV0YXRlKFNhbXBsZSA9IGFzLmNoYXJhY3RlcihTYW1wbGUpKQoKa2FibGUoQ2xlYW5EYXRhX094eWdlbikgCmBgYAoKYGBge3IgbG9hZCBDbGVhblZvbHRhZ2VEYXRhIGRpcmVjdCBmcm9tIGdvb2dsZXNoZWV0fQoKZ29vZ2xlc2hlZXRzNDo6Z3M0X2RlYXV0aCgpCgpDbGVhbkRhdGFfVm9sdGFnZSA8LSBnb29nbGVzaGVldHM0OjpyZWFkX3NoZWV0KCJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xaE5ha0N5cVBzVE5SRnBmMWxHam9CUS1wYXB5WjZ4SEtUNm1jdmgzTE1iOC9lZGl0P3BsaT0xJmdpZD04NDI5MDY5OTEjZ2lkPTg0MjkwNjk5MSIsICJDbGVhbkRhdGFfVm9sdGFnZSIpIHw+CiAgbXV0YXRlKFNhbXBsZSA9IGFzLmNoYXJhY3RlcihTYW1wbGUpKQoKa2FibGUoQ2xlYW5EYXRhX1ZvbHRhZ2UpCmBgYAoKQ29tYmluZSBPMiAmIFZvbHRhZ2UgZGF0YSBieSBzYW1wbGUgJiBkZXB0aApgYGB7ciBncmFkaWVudHNfZGZ9CkdyYWRpZW50cyA8LSBsZWZ0X2pvaW4oeCA9IENsZWFuRGF0YV9PeHlnZW4sIHkgPSBDbGVhbkRhdGFfVm9sdGFnZSwgYnkgPSBjKCJTYW1wbGUiLCAiRGVwdGhfY20iKSkKYGBgCgoKIyMgT3h5Z2VuIEdyYWRpZW50IFBsb3QKCmBgYHtyIE94eWdlbiBncmFkaWVudHN9CmdncGxvdChkYXRhID0gQ2xlYW5EYXRhX094eWdlbikgKwpnZW9tX3BvaW50KGFlcyh5ID0gRE9fwrVnX0wsIHggPSBEZXB0aF9jbSkpICsgCiAgI3NjYWxlX3lfcmV2ZXJzZSgpICsKICAjbGFicyggdGl0bGU9ICJPeHlnZW4gR3JhZGllbnRzIiwgY2FwdGlvbj0gIkZpZ3VyZSBYLiBEaXNzb2x2ZWQgT3h5Z2VuIChETykgKMK1Zy9MKSBtZWFzdXJlZCBpbiBmb3VyIFdpbm9ncmFkc2t5IGNvbHVtcyBhdCA1IGRlcHRocyAoY20pIikgCiAgIysgdGhlbWUocGxvdC5jYXB0aW9uPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBoanVzdD0wKSkgKwogICNnZW9tX3BhdGgoYWVzKHkgPSBEZXB0aF9jbSwgeCA9IERPX8K1Z19MKSkgKwogIGZhY2V0X2dyaWQoY29scyA9IHZhcnMoU2FtcGxlKSkgKwogIHRoZW1lX2J3KCkKIysgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMzAwKSkKYGBgCgpgYGB7ciBkZWNheSBmaXRzfQojZGVmaW5lIGV4cG9uZW50aWFsIGRlY2F5IGZ1bmN0aW9uIGZvciBkYXRhIGZpdHRpbmcuCmV4cF9kZWNheSA8LSBmdW5jdGlvbih4LCBpLCBtdSl7eSA9IGkgKiBleHAobXUgKiB4KX0KCgpPMl9uZXN0IDwtIENsZWFuRGF0YV9PeHlnZW4gfD4gICNhbHRlcm5hdGUgZm9yd2FyZCBwaXBlIGlzICU+JSBsb2FkZWQgd2l0aCB0aWR5dmVyc2UKICBuZXN0KC5ieSA9ICJTYW1wbGUiKSB8PgogIG11dGF0ZShEZWNheUZpdCA9IHB1cnJyOjptYXAoZGF0YSwgfm5sc0xNKERPX8K1Z19MIH4gZXhwX2RlY2F5KHggPSBEZXB0aF9jbSwgaSwgbXUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSAueCkpLAogICAgICAgICBEZWNheVRpZHkgPSBwdXJycjo6bWFwKERlY2F5Rml0LCB0aWR5KSwKICAgICAgICAgRGVjYXlQYXJhbSA9IHB1cnJyOjptYXAoRGVjYXlGaXQsIGdsYW5jZSksCiAgICAgICAgIERlY2F5UHJlZGljdCA9IHB1cnJyOjptYXAoRGVjYXlGaXQsIGF1Z21lbnQpCiAgICAgICAgICkKCiAKYGBgCgoKYGBge3IgcGxvdCBPMiBkZWNheSBmaXRzfQpPMl9uZXN0IHw+CiAgdW5uZXN0KGNvbHMgPSBjKERlY2F5UHJlZGljdCkpIHw+CiAgZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBEZXB0aF9jbSwgeSA9IERPX8K1Z19MKSkgKwogIGdlb21fbGluZShhZXMoeCA9IERlcHRoX2NtLCB5ID0gLmZpdHRlZCkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gRGVwdGhfY20sIHkgPSAucmVzaWQpLCBjb2xvdXIgPSAicmVkIikgKwogIGZhY2V0X2dyaWQoY29scyA9IHZhcnModW5saXN0KFNhbXBsZSkpKSArCiAgdGhlbWVfYncoKQpgYGAKCmBgYHtyIHNob3cgZml0IHBhcmFtZXRlcnN9Ck8yX25lc3QgfD4KdW5uZXN0KGNvbHMgPSBjKERlY2F5VGlkeSkpIHw+CiBzZWxlY3QoLWMoZGF0YSwgRGVjYXlGaXQsIERlY2F5UGFyYW0sIERlY2F5UHJlZGljdCkpIHw+CiAgc2VsZWN0KC1jKHN0YXRpc3RpYykpIHw+CiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IFNhbXBsZSwgbmFtZXNfZnJvbSA9IHRlcm0sIHZhbHVlc19mcm9tID0gYyhlc3RpbWF0ZSwgc3RkLmVycm9yLCBwLnZhbHVlKSkgfD4KICBrYWJsZSgpCmBgYAoKIyMgVm9sdGFnZSBHcmFkaWVudCBQbG90CgpgYGB7ciBQbG90dGluZyBWb2x0YWdlIEdyYWRpZW50cyBpbiB3YXRlciBhdCAxMCBzZWNvbmRzfQoKZ2dwbG90KGRhdGEgPSBHcmFkaWVudHMpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gRGVwdGhfY20sIHkgPSBWb2x0YWdlX1dhdGVyXzEwc19tdikpICsgCiAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyhTYW1wbGUpKSArIAogIHRoZW1lX2J3KCkKYGBgCgoKYGBge3IgUGxvdHRpbmcgV2l0aCBhIGxpbmVhciBmaXR9CgogIExpbmVhcl9maXQgPC0gR3JhZGllbnRzICU+JSAKICBncm91cF9ieShTYW1wbGUpICU+JQogIGdyb3VwX21vZGlmeSh+IHsKCiAgbGluZWFyIDwtIGxtKFZvbHRhZ2VfV2F0ZXJfMTBzX212IH4gRGVwdGhfY20sIGRhdGEgPSAueCwgbmEuYWN0aW9uID0gbmEuZXhjbHVkZSkKICBhdWdtZW50KGxpbmVhciwgZGF0YSA9IC54KX0pICU+JQogIHVuZ3JvdXAoKQoKCiAgTGluZWFyX2ZpdCB8PiAgIAogICAgZ2dwbG90KGFlcyh4ID0gRGVwdGhfY20sIHkgPSBWb2x0YWdlX1dhdGVyXzEwc19tdikpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX2xpbmUoYWVzKHkgPSAuZml0dGVkKSkgKwogICAgI1Nob3dpbmcgcmVzaWR1YWxzCiAgICAjZ2VvbV9wb2ludChhZXMoeCA9IERlcHRoX2NtLCB5ID0gLnJlc2lkKSwgY29sb3VyID0gInJlZCIpICsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9IERlcHRoX2NtLCB5ZW5kID0gLmZpdHRlZCksIGNvbG9yID0gInJlZCIpICsKICAgIGZhY2V0X2dyaWQoY29scyA9IHZhcnModW5saXN0KFNhbXBsZSkpKSArCiAgICB0aGVtZV9idygpCgoKYGBgCgoKYGBge3IgRXhhbWluaW5nIGxpbmVhciBmaXQgcGFyYW1ldGVyc30KIApMaW5lYXJfZml0X3BhcmFtIDwtIExpbmVhcl9maXQgfD4KICBncm91cF9ieShTYW1wbGUpIHw+CiAgZ3JvdXBfbW9kaWZ5KH4gewogICAgbGluZWFyX21vZGVsIDwtIGxtKFZvbHRhZ2VfV2F0ZXJfMTBzX212IH4gRGVwdGhfY20sIGRhdGEgPSAueCkKICAgIHRpZHlfbW9kZWwgPC0gdGlkeShsaW5lYXJfbW9kZWwpICAKICAgIHRpZHlfbW9kZWwkU2FtcGxlIDwtIHVuaXF1ZSgueCRTYW1wbGUpICAjIEVuc3VyZSBTYW1wbGUgY29sdW1uIGlzIGFkZGVkCiAgICByZXR1cm4odGlkeV9tb2RlbCkgIAogIH0pIHw+CiAgdW5ncm91cCgpIAoKTGluZWFyX2ZpdF9wYXJhbSA8LSBMaW5lYXJfZml0X3BhcmFtIHw+CiAgbXV0YXRlKHRlcm0gPSBzdHJfcmVwbGFjZSh0ZXJtLCAiXFwoSW50ZXJjZXB0XFwpIiwgIkkiKSkKCkxpbmVhcl9maXRfcGFyYW0gfD4KICBzZWxlY3QoLWMoc3RhdGlzdGljKSkgfD4KICBwaXZvdF93aWRlcihpZF9jb2xzID0gU2FtcGxlLCBuYW1lc19mcm9tID0gdGVybSwgdmFsdWVzX2Zyb20gPSBjKGVzdGltYXRlLCBzdGQuZXJyb3IsIHAudmFsdWUpKSB8PgogIGthYmxlKCkKIApgYGAKCiMjIE94eWdlbiBhbmQgVm9sdGFnZSBHcmFkaWVudHMKCmBgYHtyIG94eWdlbiBhbmQgdm9sdGFnZSBncmFkaWVudHN9CgogICAgT3h5Z2VuIDwtIGdncGxvdChkYXRhID0gR3JhZGllbnRzKSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBEZXB0aF9jbSwgeSA9IERPX8K1Z19MKSkgKwogICAgICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKFNhbXBsZSkpICsgCiAgICAgIHRoZW1lX2J3KCkKCiAgICBWb2x0YWdlIDwtIGdncGxvdChkYXRhID0gR3JhZGllbnRzKSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBEZXB0aF9jbSwgeSA9IFZvbHRhZ2VfV2F0ZXJfMTBzX212KSkgKwogICAgICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKFNhbXBsZSkpICsgCiAgICAgIHRoZW1lX2J3KCkKICAgICAgCiAgcHJpbnQoT3h5Z2VuL1ZvbHRhZ2UpCiAgCiAgCmBgYAoKCgo=
LS0tDQp0aXRsZTogIk94eWdlbiZWb2x0YWdlX2dyYWRpZW50cyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgSW50cm9kdWN0aW9uDQoNClRoaXMgcm1kLiBmaWxlIGltcG9ydHMgb3h5Z2VuIGFuZCB2b2x0YWdlIGRhdGEgZnJvbSBHb29nbGUgc2hlZXQNCkRhdGEgaXMgdXNlZCB0byBwbG90IGEgb3h5Z2VuIGFuZCB2b2x0YWdlIGdyYWRpZW50IG1hcCBvZiB0aGUgd2lub2dyYWRza3kgY29sdW1uIA0KRXhwb25lbnRpYWwgYW5kIGxpbmVhciBtb2RlbHMgd2VyZSB1c2VkIHRvIGFuYWx5emUgZGF0YQ0KDQojTG9hZGluZyBQYWNrYWdlcyANCg0KYGBge3IgbG9hZGluZyBwYWNrYWdlc30NCmxpYnJhcnkodGlkeXZlcnNlKSANCmxpYnJhcnkoZ29vZ2xlZHJpdmUpIA0KbGlicmFyeShnb29nbGVzaGVldHM0KQ0KI2xpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KG1pbnBhY2subG0pDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShwdXJycikNCmxpYnJhcnkobG1lNCkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KYGBgDQoNCiNJbXBvcnRpbmcgZnJvbSBnb29nbGUgc2hlZXQNCg0KYGBge3IgbG9hZCBDbGVhbk94eWdlbkRhdGEgZGlyZWN0IGZyb20gZ29vZ2xlc2hlZXR9DQoNCmdvb2dsZXNoZWV0czQ6OmdzNF9kZWF1dGgoKQ0KDQpDbGVhbkRhdGFfT3h5Z2VuIDwtIGdvb2dsZXNoZWV0czQ6OnJlYWRfc2hlZXQoImh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFoTmFrQ3lxUHNUTlJGcGYxbEdqb0JRLXBhcHlaNnhIS1Q2bWN2aDNMTWI4L2VkaXQ/cGxpPTEmZ2lkPTg0MjkwNjk5MSNnaWQ9ODQyOTA2OTkxIiwgIkNsZWFuRGF0YV9PeHlnZW4iKSB8Pg0KICBtdXRhdGUoU2FtcGxlID0gYXMuY2hhcmFjdGVyKFNhbXBsZSkpDQoNCmthYmxlKENsZWFuRGF0YV9PeHlnZW4pIA0KYGBgDQoNCmBgYHtyIGxvYWQgQ2xlYW5Wb2x0YWdlRGF0YSBkaXJlY3QgZnJvbSBnb29nbGVzaGVldH0NCg0KZ29vZ2xlc2hlZXRzNDo6Z3M0X2RlYXV0aCgpDQoNCkNsZWFuRGF0YV9Wb2x0YWdlIDwtIGdvb2dsZXNoZWV0czQ6OnJlYWRfc2hlZXQoImh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFoTmFrQ3lxUHNUTlJGcGYxbEdqb0JRLXBhcHlaNnhIS1Q2bWN2aDNMTWI4L2VkaXQ/cGxpPTEmZ2lkPTg0MjkwNjk5MSNnaWQ9ODQyOTA2OTkxIiwgIkNsZWFuRGF0YV9Wb2x0YWdlIikgfD4NCiAgbXV0YXRlKFNhbXBsZSA9IGFzLmNoYXJhY3RlcihTYW1wbGUpKQ0KDQprYWJsZShDbGVhbkRhdGFfVm9sdGFnZSkNCmBgYA0KDQpDb21iaW5lIE8yICYgVm9sdGFnZSBkYXRhIGJ5IHNhbXBsZSAmIGRlcHRoDQpgYGB7ciBncmFkaWVudHNfZGZ9DQpHcmFkaWVudHMgPC0gbGVmdF9qb2luKHggPSBDbGVhbkRhdGFfT3h5Z2VuLCB5ID0gQ2xlYW5EYXRhX1ZvbHRhZ2UsIGJ5ID0gYygiU2FtcGxlIiwgIkRlcHRoX2NtIikpDQpgYGANCg0KDQojT3h5Z2VuIEdyYWRpZW50IFBsb3QNCg0KYGBge3IgT3h5Z2VuIGdyYWRpZW50c30NCmdncGxvdChkYXRhID0gQ2xlYW5EYXRhX094eWdlbikgKw0KZ2VvbV9wb2ludChhZXMoeSA9IERPX8K1Z19MLCB4ID0gRGVwdGhfY20pKSArIA0KICAjc2NhbGVfeV9yZXZlcnNlKCkgKw0KICAjbGFicyggdGl0bGU9ICJPeHlnZW4gR3JhZGllbnRzIiwgY2FwdGlvbj0gIkZpZ3VyZSBYLiBEaXNzb2x2ZWQgT3h5Z2VuIChETykgKMK1Zy9MKSBtZWFzdXJlZCBpbiBmb3VyIFdpbm9ncmFkc2t5IGNvbHVtcyBhdCA1IGRlcHRocyAoY20pIikgDQogICMrIHRoZW1lKHBsb3QuY2FwdGlvbj0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSwgaGp1c3Q9MCkpICsNCiAgI2dlb21fcGF0aChhZXMoeSA9IERlcHRoX2NtLCB4ID0gRE9fwrVnX0wpKSArDQogIGZhY2V0X2dyaWQoY29scyA9IHZhcnMoU2FtcGxlKSkgKw0KICB0aGVtZV9idygpDQojKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAzMDApKQ0KYGBgDQoNCmBgYHtyIGRlY2F5IGZpdHN9DQojZGVmaW5lIGV4cG9uZW50aWFsIGRlY2F5IGZ1bmN0aW9uIGZvciBkYXRhIGZpdHRpbmcuDQpleHBfZGVjYXkgPC0gZnVuY3Rpb24oeCwgaSwgbXUpe3kgPSBpICogZXhwKG11ICogeCl9DQoNCg0KTzJfbmVzdCA8LSBDbGVhbkRhdGFfT3h5Z2VuIHw+ICAjYWx0ZXJuYXRlIGZvcndhcmQgcGlwZSBpcyAlPiUgbG9hZGVkIHdpdGggdGlkeXZlcnNlDQogIG5lc3QoLmJ5ID0gIlNhbXBsZSIpIHw+DQogIG11dGF0ZShEZWNheUZpdCA9IHB1cnJyOjptYXAoZGF0YSwgfm5sc0xNKERPX8K1Z19MIH4gZXhwX2RlY2F5KHggPSBEZXB0aF9jbSwgaSwgbXUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gLngpKSwNCiAgICAgICAgIERlY2F5VGlkeSA9IHB1cnJyOjptYXAoRGVjYXlGaXQsIHRpZHkpLA0KICAgICAgICAgRGVjYXlQYXJhbSA9IHB1cnJyOjptYXAoRGVjYXlGaXQsIGdsYW5jZSksDQogICAgICAgICBEZWNheVByZWRpY3QgPSBwdXJycjo6bWFwKERlY2F5Rml0LCBhdWdtZW50KQ0KICAgICAgICAgKQ0KDQogDQpgYGANCg0KDQpgYGB7ciBwbG90IE8yIGRlY2F5IGZpdHN9DQpPMl9uZXN0IHw+DQogIHVubmVzdChjb2xzID0gYyhEZWNheVByZWRpY3QpKSB8Pg0KICBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBEZXB0aF9jbSwgeSA9IERPX8K1Z19MKSkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBEZXB0aF9jbSwgeSA9IC5maXR0ZWQpKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBEZXB0aF9jbSwgeSA9IC5yZXNpZCksIGNvbG91ciA9ICJyZWQiKSArDQogIGZhY2V0X2dyaWQoY29scyA9IHZhcnModW5saXN0KFNhbXBsZSkpKSArDQogIHRoZW1lX2J3KCkNCmBgYA0KDQpgYGB7ciBzaG93IGZpdCBwYXJhbWV0ZXJzfQ0KTzJfbmVzdCB8Pg0KdW5uZXN0KGNvbHMgPSBjKERlY2F5VGlkeSkpIHw+DQogc2VsZWN0KC1jKGRhdGEsIERlY2F5Rml0LCBEZWNheVBhcmFtLCBEZWNheVByZWRpY3QpKSB8Pg0KICBzZWxlY3QoLWMoc3RhdGlzdGljKSkgfD4NCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IFNhbXBsZSwgbmFtZXNfZnJvbSA9IHRlcm0sIHZhbHVlc19mcm9tID0gYyhlc3RpbWF0ZSwgc3RkLmVycm9yLCBwLnZhbHVlKSkgfD4NCiAga2FibGUoKQ0KYGBgDQoNCiMgVm9sdGFnZSBHcmFkaWVudCBQbG90DQoNCmBgYHtyIFBsb3R0aW5nIFZvbHRhZ2UgR3JhZGllbnRzIGluIHdhdGVyIGF0IDEwIHNlY29uZHN9DQoNCmdncGxvdChkYXRhID0gR3JhZGllbnRzKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSBEZXB0aF9jbSwgeSA9IFZvbHRhZ2VfV2F0ZXJfMTBzX212KSkgKyANCiAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyhTYW1wbGUpKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KDQpgYGB7ciBQbG90dGluZyBXaXRoIGEgbGluZWFyIGZpdH0NCg0KICBMaW5lYXJfZml0IDwtIEdyYWRpZW50cyAlPiUgDQogIGdyb3VwX2J5KFNhbXBsZSkgJT4lDQogIGdyb3VwX21vZGlmeSh+IHsNCg0KICBsaW5lYXIgPC0gbG0oVm9sdGFnZV9XYXRlcl8xMHNfbXYgfiBEZXB0aF9jbSwgZGF0YSA9IC54LCBuYS5hY3Rpb24gPSBuYS5leGNsdWRlKQ0KICBhdWdtZW50KGxpbmVhciwgZGF0YSA9IC54KX0pICU+JQ0KICB1bmdyb3VwKCkNCg0KDQogIExpbmVhcl9maXQgfD4gICANCiAgICBnZ3Bsb3QoYWVzKHggPSBEZXB0aF9jbSwgeSA9IFZvbHRhZ2VfV2F0ZXJfMTBzX212KSkgKw0KICAgIGdlb21fcG9pbnQoKSArDQogICAgZ2VvbV9saW5lKGFlcyh5ID0gLmZpdHRlZCkpICsNCiAgICAjU2hvd2luZyByZXNpZHVhbHMNCiAgICAjZ2VvbV9wb2ludChhZXMoeCA9IERlcHRoX2NtLCB5ID0gLnJlc2lkKSwgY29sb3VyID0gInJlZCIpICsNCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBEZXB0aF9jbSwgeWVuZCA9IC5maXR0ZWQpLCBjb2xvciA9ICJyZWQiKSArDQogICAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyh1bmxpc3QoU2FtcGxlKSkpICsNCiAgICB0aGVtZV9idygpDQoNCg0KYGBgDQoNCg0KYGBge3IgR2VuZXJhdGluZyB0aGUgbGluZWFyIG1vZGVsIGZvciB0aGUgcGxvdHN9DQogDQogTGluZWFyX2ZpdF9yZXN1bHRzIDwtIExpbmVhcl9maXQgfD4NCiAgIGdyb3VwX2J5KFNhbXBsZSkgfD4NCiAgIGdyb3VwX21vZGlmeSh+IHsNCiAgICBsaW5lYXJfbW9kZWwgPC0gbG0oVm9sdGFnZV9XYXRlcl8xMHNfbXYgfiBEZXB0aF9jbSwgZGF0YSA9IC54KQ0KICAgIHRpZHlfbW9kZWwgPC0gdGlkeShsaW5lYXJfbW9kZWwpICANCiAgICB0aWR5X21vZGVsJFNhbXBsZSA8LSB1bmlxdWUoLngkU2FtcGxlKSAgDQogICAgcmV0dXJuKHRpZHlfbW9kZWwpICANCiAgIH0pIHw+DQogIHVuZ3JvdXAoKSB8Pg0KICAjIEZpbHRlciBmb3IgJ0RlcHRoX2NtJyBjb2VmZmljaWVudCAod2UgYXJlIGV4YW1pbmluZyBWb2x0YWdlIGluIHRlcm1zIG9mIERlcHRoX2NtKQ0KICBmaWx0ZXIodGVybSA9PSAiRGVwdGhfY20iKSAgDQoNCiMgU2VsZWN0aW5nIHRvIGluY2x1ZGUgU2FtcGxlLCBlc3RpbWF0ZSBvZiBzbG9wZSwgc3RkLmVycm9yLCBhbmQgcC52YWx1ZSBpbiB0YWJsZSBvdXRwdXQNCkxpbmVhcl9maXRfcmVzdWx0cyB8Pg0KICBzZWxlY3QoU2FtcGxlLCBlc3RpbWF0ZSwgc3RkLmVycm9yLCBwLnZhbHVlKSANCiANCiNEaXNwbGF5aW5nIHRoZSB0YWJsZSBhbmQgc3BlY2lmeWluZyBzaWcgZGlnaXRzIHNob3duDQogTGluZWFyX2ZpdCB8Pg0KICBrYWJsZShkaWdpdHM9MykNCg0KYGBgDQoNCiMjIE94eWdlbiB2cyBWb2x0YWdlIEdyYXBocw0KDQpgYGB7ciBveHlnZW4gdnMgdm9sdGFnZX0NCg0KICAgIE94eWdlbiA8LSBnZ3Bsb3QoZGF0YSA9IEdyYWRpZW50cykgKw0KICAgICAgZ2VvbV9wb2ludChhZXMoeCA9IERlcHRoX2NtLCB5ID0gRE9fwrVnX0wpKSArDQogICAgICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKFNhbXBsZSkpICsgDQogICAgICB0aGVtZV9idygpDQoNCiAgICBWb2x0YWdlIDwtIGdncGxvdChkYXRhID0gR3JhZGllbnRzKSArDQogICAgICBnZW9tX3BvaW50KGFlcyh4ID0gRGVwdGhfY20sIHkgPSBWb2x0YWdlX1dhdGVyXzEwc19tdikpICsNCiAgICAgIGZhY2V0X2dyaWQoY29scyA9IHZhcnMoU2FtcGxlKSkgKyANCiAgICAgIHRoZW1lX2J3KCkNCiAgICAgIA0KICBwcmludChPeHlnZW4vVm9sdGFnZSkNCiAgDQogIA0KYGBgDQoNCg0KYGBge3IgT3h5Z2VuIGFuZCBWb2x0YWdlIHJlbGF0aW9uc2hpcH0NCg0KZ2dwbG90KGRhdGEgPSBHcmFkaWVudHMpICsNCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBET1/CtWdfTCwgeSA9IFZvbHRhZ2VfV2F0ZXJfMTBzX212KSkgKw0KICAgICAgZ2VvbV9zbW9vdGgoYWVzKHggPSBET1/CtWdfTCwgeSA9IFZvbHRhZ2VfV2F0ZXJfMTBzX212KSwgbWV0aG9kID0gImxtIikgKw0KICAgICAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyhTYW1wbGUpKSArIA0KICAgICAgdGhlbWVfYncoKQ0KDQpgYGANCg0KDQoNCg0KIyBDYW4gb25seSBpbXBvcnQgb25lIGltYWdlIGF0IGEgdGltZSByaWdodCBub3csIHdlIGNvdWxkIGNob29zZSBzb21lIG5vdGFibGUgb25lcyB0byBkaXNwbGF5Pw0KYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIiwgZmlnLmNhcD0iTXkgSW1hZ2UifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uL2RvY3MvU2xpZGVQaG90b3MvMTAwMV82LjZfQy5qcGciKQ0KYGBgDQoNCg==